package com.yilin.platform.base_core.commons.utils;


import java.math.BigDecimal;

public class MathUtil {
    /**
     * 默认除法运算精度
     */
    private static final int DEFAULT_DIV_SCALE = 10;

    /**
     * 平均分配
     * */
    public static double average(double total, int length, int i) {
        double divide = MathUtil.divide(total, length * 1.00D,2);
        if (i < length-1) return MathUtil.round(divide,2);
        return MathUtil.subtract(total, MathUtil.multiply(divide,(length-1)*1.00D,2));
    }

    //连加
    public static double add(Double num1, Double... nums) {
        if (num1 == null) num1 = 0.00;
        if (nums.length == 0) return num1;
        BigDecimal decimal = new BigDecimal(String.valueOf(num1));
        for (Double num : nums) {
            if (num == null) num = 0.0D;
            BigDecimal decimal2 = new BigDecimal(String.valueOf(num));
            decimal = decimal.add(decimal2);
        }
        return decimal.doubleValue();
    }

    //连减
    public static double subtract(Double num1, Double... nums) {
        if (num1 == null) num1 = 0.00;
        if (nums.length == 0) return num1;
        BigDecimal decimal = new BigDecimal(String.valueOf(num1));
        for (Double num : nums) {
            if (num == null) num = 0.0D;
            BigDecimal decimal2 = new BigDecimal(String.valueOf(num));
            decimal = decimal.subtract(decimal2);
        }
        return decimal.doubleValue();
    }
    /**
     * 提供精确的乘法运算,如果由一个值不为number 则返回0
     *
     * @param v1 参数1
     * @param v2 参数2
     * @return 两个参数的积，以字符串格式返回
     */
    public static Integer multiplyInt(Double v1, Double v2) {
        if (v1 == null || v2 == null) return null;
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return Integer.valueOf(b1.multiply(b2).setScale(0, BigDecimal.ROUND_HALF_EVEN).toString());
    }

    /**
     * 提供精确的加法运算
     */
    public static String add(String v1, String v2) {
        BigDecimal b1 = new BigDecimal(v1);
        BigDecimal b2 = new BigDecimal(v2);
        return b1.add(b2).toString();
    }

    /**
     * 除以：：提供（相对）精确的除法运算，当发生除不尽的情况时，四舍六入五奇上偶下
     */
    public static double divide(Double num1, Double num2, int scale) {
        if (num1 == null) num1 = 0.00;
        if (num2 == null) num2 = 0.00;
        BigDecimal decimal1 = new BigDecimal(String.valueOf(num1));
        BigDecimal decimal2 = new BigDecimal(String.valueOf(num2));
        return decimal1.divide(decimal2,scale, BigDecimal.ROUND_HALF_EVEN).doubleValue();
    }

//    /**
//     * 除以：：提供（相对）精确的除法运算，当发生除不尽的情况时，向上
//     */
//    public static double divideHalfUp(Double v1, Double v2, int scale) {
//        if (v1 == null) v1 = 0.00;
//        if (v2 == null || v2== 0 ) return  0.00;
//        return MathUtil.divide(v1, v2, scale, BigDecimal.ROUND_HALF_UP);
//    }
//
//    /**
//     * 除以：：提供（相对）精确的除法运算，当发生除不尽的情况时，向上
//     */
//    public static double divideHalfDown(Double v1, Double v2, int scale) {
//        if (v1 == null) v1 = 0.00;
//        if (v2 == null) v2 = 0.00;
//        return MathUtil.divide(v1, v2, scale, BigDecimal.ROUND_HALF_UP);
//    }

    /**
     * 乘以：：提供精确的乘法运算
     */
    public static double multiply(Double num1, Double num2, int scale) {
        if (num1 == null) num1 = 0.00;
        if (num2 == null) num2 = 0.00;
        BigDecimal decimal1 = new BigDecimal(String.valueOf(num1));
        BigDecimal decimal2 = new BigDecimal(String.valueOf(num2));
        return decimal1.multiply(decimal2).setScale(scale, BigDecimal.ROUND_HALF_EVEN).doubleValue();
    }

//    /**
//     * 乘以：：提供精确的乘法运算 向上
//     */
//    public static double multiplyUp(Double v1, Double v2, int scale) {
//        if (v1==null) v1 = 0d; if (v2==null) v2 = 0d;
//        BigDecimal b1 = new BigDecimal(Double.toString(v1));
//        BigDecimal b2 = new BigDecimal(Double.toString(v2));
//        return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP).doubleValue();
//    }
//
//    /**
//     * 乘以：：提供精确的乘法运算 向上
//     */
//    public static double multiplyDown(double v1, double v2, int scale) {
//        BigDecimal b1 = new BigDecimal(Double.toString(v1));
//        BigDecimal b2 = new BigDecimal(Double.toString(v2));
//        return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_DOWN).doubleValue();
//    }

    /**
     * 提供精确的小数位 向上
     */
    public static double round(double v, int scale) {
        return MathUtil.round(v, scale, BigDecimal.ROUND_HALF_EVEN);
    }


    /**
     * 提供精确的小数位四舍五入处理，舍入模式采用用户指定舍入模式
     */
    private static double round(double v, int scale, int round_mode) {
        MathUtil.scaleCheck(scale);
        BigDecimal b = new BigDecimal(Double.toString(v));
        return b.setScale(scale, round_mode).doubleValue();
    }
    /**
     * 提供精确的小数位四舍五入处理，舍入模式采用用户指定舍入模式
     */
    public static double round(Object s, int scale, int round_mode) {
        String  v=String.valueOf(s);
        MathUtil.scaleCheck(scale);
        BigDecimal b = new BigDecimal(v);
        return b.setScale(scale, round_mode).doubleValue();
    }
//    /**
//     * 向上取整
//     */
//    public static Double doubleHalfUp(Double value, int i) {
//        if (value == null) value = 0D;
//        BigDecimal two = new BigDecimal(value);
//        return two.setScale(i, BigDecimal.ROUND_HALF_UP).doubleValue();
//    }
//    /**
//     * 向下取整
//     */
//    public static Double doubleHalfDown(Double value, int i) {
//        if (value == null) value = 0D;
//        BigDecimal two = new BigDecimal(value);
//        return two.setScale(i, BigDecimal.ROUND_HALF_DOWN).doubleValue();
//    }


    private static double divide(double v1, double v2, int scale, int round_mode) {
        MathUtil.scaleCheck(scale);
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2, scale, round_mode).doubleValue();
    }
    private static void scaleCheck(int scale) {
        if (scale < 0) {
            String msg = "The scale must be a positive integer or zero";
            throw new IllegalArgumentException(msg);
        }
    }

}
